#include <iostream>
#include <time.h>
#include <stdio.h>
#include <sys/time.h>
#include <string>
#include <vector>
#include <map>
#include <fstream>
#include <stdlib.h>
#include <sstream>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <assert.h>
#include <set>

#ifndef _tm_processor_h
#define _tm_processor_h

using namespace std;

 // MAX_SLOTS * (1000 / slotDuration) = longgest tracking time
#define MAX_SLOTS 5000
#define output_appendx "_timeline_output.csv"
#define output_delimiter ','

enum Status{
	END_OR_WAIT = 0,
	BEGIN_OR_ALIVE = 1
};

class Error{
public:
	Error(string str){ whatHappened = str;};
	void what(){ cout<<whatHappened<<endl;};
	string whatHappened;
};

#define PR(msg) \
	{\
	time_t t = time(NULL); \
	char buf[26]; \
	ctime_r(&t,buf); \
	buf[24] = 0; \
	cout<<buf<<"@"<<__FILE__<<__LINE__<<">"<<msg<<endl;\
	}

#define PARAM_COUT(msg)\
	{\
		cout<<"   PARAM_COUT("<<#msg<<")@"<<__FILE__<<__LINE__<<"\n   ..:"<<msg<<endl; \
	}

struct SlotInfo{
	float slotBeginTime;
	Status status;
};

struct TrackLine{
	string name;
        // [MainThread B 13.31] ->  {13.31,BEGIN_OR_ALIVE}
        //use MAP to auto-sort time Stamps
	map<float,Status> timeStamps;

        //eg, sliceFactor = 500ms
        // [[MainThread B 13.0]]
        // [[MainThread E 14.0]]
        //             ->
        //...  {13.0,1},{13.5,1},{14.0,1}, {14.5,0}
        //When get a 'Begin', change status to 1 from this slice.
        //When get a 'End', change status to 0 from next slice.  
	vector<SlotInfo> slotInfos;
};

//[[MainThread B 12.12]]
//[[MainThread E 13.31]]
//[[SName SStatus STime]]
//loader: extract timeline content from trace, merge timestamp by SNAME
//parser: analysis timestamp for each SNAME, then generate time line to describe if the 
//process is alive or sleep during the traced period.
//writer: output analysis report to file. The file is used to generate graph by Excel-like programe.
class Processor{
public:
	Processor(const string _fileName, int _sliceFactor){ 
		PARAM_COUT(_fileName);
		PARAM_COUT(_sliceFactor);
		fileName = _fileName;
		slotDuration = _sliceFactor;
                slotCount = 0;
	}
	~Processor();
    
//pre-assumption:
//No Space within SName.
// [[ ]] pair exist in same line
	bool loadFile();
	bool parseSlots();
        bool parseOneLine(TrackLine* tline, float trackAreaBegin, float trackAreaEnd);
	bool output();
	
private:
	vector <TrackLine*> lines;
	string fileName;
	int slotDuration;//unit: ms
	unsigned  slotCount;//calculated value, sizeof slotInfos of each Track line
private:
	//check if s have [[ .. ]] pair, then remove the brackets.
	bool trim(std::string &s);

	// [[MainThread E 14.0]]
	bool validate(const string s, float& sTime, Status & sStat, string& sectionName);
	void merge(const float& sTime, const Status & sStat, const string& sectionName);
        int 	createSlots(float begin,float end, vector<SlotInfo> & slots);
        float findSlot(float input);//useless

	void displayLine(TrackLine & in);
};

#endif

